import json
import os.path
from pathlib import Path
from typing import Set, Dict, List

from fontTools.ttLib import TTFont, TTCollection
from loguru import logger


def save_font_support_chars(root_folder, out_folder):
    if not os.path.exists(out_folder):
        os.mkdir(out_folder)
    font_support_chars_cache: Dict[str, Set] = load_font_support_chars(root_folder)
    char_list: Dict[str, List] = {}
    for path in font_support_chars_cache:
        char_list[path] = list(font_support_chars_cache[path])
        path_ = Path(path)
        file_name = path_.name
        try:
            with open(out_folder + file_name + '.json', "w", encoding='utf-8') as f:
                json.dump(char_list, f, indent=4, ensure_ascii=False, sort_keys=True)
        except:
            print(file_name)
        else:
            print(file_name)


def load_font_support_chars(root_folder):
    font_paths = get_font_list_from_folder(root_folder)
    font_support_chars_cache: Dict[str, Set] = {}
    for font_path in font_paths:
        ttf = load_ttfont(font_path)

        chars_int = set()
        try:
            for table in ttf["cmap"].tables:
                for k, v in table.cmap.items():
                    chars_int.add(k)
        except AssertionError as e:
            logger.error(f"Load font file {font_path} failed, skip it. Error: {e}")

        supported_chars = set([chr(c_int) for c_int in chars_int])

        ttf.close()

        font_support_chars_cache[font_path] = supported_chars
    return font_support_chars_cache


def get_font_list_from_folder(root_folder):
    font_paths: List[str] = []
    font_dir = Path(root_folder)
    for font_path in font_dir.glob("**/*"):
        if font_path.suffix in [".ttc", ".TTC", ".ttf", ".TTF", ".otf", ".OTF"]:
            font_paths.append(str(font_path))
    return font_paths


def load_ttfont(font_path: str) -> TTFont:
    """
    Read ttc, ttf, otf font file, return a TTFont object
    """

    # ttc is collection of ttf
    if font_path.endswith("ttc"):
        ttc = TTCollection(font_path)
        # assume all ttfs in ttc file have same supported chars
        return ttc.fonts[0]

    if (
            font_path.endswith("ttf")
            or font_path.endswith("TTF")
            or font_path.endswith("otf")
    ):
        ttf = TTFont(
            font_path, 0, allowVID=0, ignoreDecompileErrors=True, fontNumber=-1
        )

        return ttf


if __name__ == '__main__':
    # load_font_support_chars(r'C:\Windows\Fonts')
    save_font_support_chars(r'C:/Windows/Fonts', r'D:/ocr/ocr_resources/reader/all_words/font_chars/')
